package com.rainbow.common.handler.filter;

import com.rainbow.common.core.constant.Constant;
import com.rainbow.common.handler.wrapper.RequestHeaderWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 将网关生成得全局日志放入MDC
 * 服务调用时,日志关联到TraceId
 * 目前需要排除nacos服务通讯地址
 * @author 傅为地
 */
@Slf4j
public class TraceFilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String[] noFilterUrls=super.getFilterConfig().getInitParameter("noTraceUrls").split(",");
        List<String> noFilterList = new ArrayList(Arrays.asList(noFilterUrls)) ;
        //放行路径直接不加traceId
        /*log.warn("TRACE==>地址:{},header:{},MDC:{}",request.getRequestURI(),request.getHeader(Constant.GLOBAL_LOG_PREFIX),MDC.get(Constant.GLOBAL_LOG_PREFIX));*/
        String url=request.getRequestURI();
        Boolean isOk=noFilterList.stream().anyMatch(t->ObjectUtils.isNotEmpty(t)&& StringUtils.containsIgnoreCase(url, t));
        //放行路径不加traceId
        if(isOk){
            filterChain.doFilter(request, response);
        }else{
            String traceId = ObjectUtils.isEmpty(request.getHeader(Constant.GLOBAL_LOG_PREFIX)) ? TraceContext.traceId() : request.getHeader(Constant.GLOBAL_LOG_PREFIX);
            //网关生成得全局日志放入MDC,后续服务可以全局日志统一
            MDC.put(Constant.GLOBAL_LOG_PREFIX, traceId);
            //自定义trace传递header参数
            RequestHeaderWrapper requestWarpper=new RequestHeaderWrapper(request);
            requestWarpper.addHeader(Constant.GLOBAL_LOG_PREFIX, traceId);
            if(ObjectUtils.isNotEmpty(request.getHeader(Constant.AUTHORIZATION))){
                requestWarpper.addHeader(Constant.AUTHORIZATION, request.getHeader(Constant.AUTHORIZATION));
            }
            if(ObjectUtils.isNotEmpty(request.getHeader(Constant.SERVICE_VERSION))){
                requestWarpper.addHeader(Constant.SERVICE_VERSION, request.getHeader(Constant.SERVICE_VERSION));
            }
            if(ObjectUtils.isNotEmpty(request.getHeader(Constant.USER_TOKEN_CLIENT_ID))){
                requestWarpper.addHeader(Constant.USER_TOKEN_CLIENT_ID, request.getHeader(Constant.USER_TOKEN_CLIENT_ID));
            }
            filterChain.doFilter(requestWarpper, response);
        }
    }
}
